org 0x7c00
jmp short start ;jmp 一个字节 短跳转1个字节 剩下一个字节用nop 跳转
nop

;定义fat32文件头部
header:
  BS_OEMNAME db "D.T.Soft"
  BPB_BytsPersec dw 512
  BPB_SecPerClus db 1
  BPB_RsvdSecCnt dw 1
  BPB_NumFATS    db 2
  BPB_RootEntCnt dw 224
  BPB_TotSec16   dw 2880
  BPB_Media      db 0xF0
  BPB_FATSz16    dw 9
  BPB_SecPerTrk  dw 18
  BPB_NumHeads   dw 2
  BPB_HiddSec    dd 0
  BPB_TotSec32   dd 0
  BS_DrvNum      db 0
  BS_Reserved1   db 0
  BS_BootSig     db 0x29
  BS_VolID       dd 0
  BS_VOlLab      db "D.T.OS-0.01"
  BS_FileSysType db "FAT12"

;定义栈顶基地址
define:
 BaseOfStack equ 0x7c00
 RootEntryOffset equ 19
 RootEntryLength equ 14

start:;初始化寄存器
  mov ax, cs
  mov ss, ax
  mov ds, ax
  mov es, ax
  mov sp, BaseOfStack 

  ;测试 ReadSector 函数
  ;mov ax,43;//读取内容扇区个数偏移 作为参数
  ;mov cx,1;//读取一个扇区的数据 作为函数参数
  ;mov bx,Buf;读到buf里面 buf地址给bx ReadSector 函数写入bx的数据相当于写入buf
  ;call ReadSector;测试函数
  ;mov bp, Buf;指定段偏移地址
  ;mov cx,29;打印字符串的个数
  ;call Print

  ;测试MemCmp函数 
  ;mov si, MsgStr
  ;mov di, DEST
  ;mov cx, MsgLen
  ;call MemCmp
  ;cmp cx,0
  ;jz label
  ;jmp last

  ;加载根目录区
  mov ax,RootEntryOffset
  mov cx,RootEntryLength
  mov bx,Buf
  call ReadSector

  mov si,DEST
  mov cx,TarLen
  mov dx,0
  call FindEntry
  cmp dx,0
  jz output
  jmp last

output:
label:
  mov bp, MsgStr
  mov cx,MsgLen
  call Print
  
last:
  hlt
  jmp last


;es:bx---->root entry offset addr
;ds:si----->target string
;cx ---> target len
;return:
;dx != 0 ?exisit:noexisit
;exist--->bx is the target entry
FindEntry:
  push di;
  push bp;
  push cx; 目标字符串长度 入栈
  ;dx 是返回值 不需要保存

  
  mov dx,[BPB_RootEntCnt] ;最大查找次数
  mov bp,sp ;访问栈顶 为了访问目标字符串 的长度
find:
  cmp dx,0
  jz noexist

  mov di,bx; 根目录起始地址
  mov cx,[bp]
  ;si 再调用FindEntry已经指定过了
  call MemCmp 
  cmp cx,0
  jz exist
  add bx,32 ;查找下一项 如果每找到
  dec dx;项数-1
  jmp find

noexist:
exist:
  pop cx
  pop bp
  pop di
  ret

;ds:si -->source
;es:di -->destination
;cx --->length
;return:
; cx==0 ?equal : noequal
MemCmp:
  push si
  push di
  push ax
  ;cx 为什么没有 保存堆栈 是因为cx 作为返回值使用 cx == 0 就是相等 cx != 0就是不相等
compare:
  cmp cx,0
  jz equal
  mov al,[si]
  cmp al,byte [di];指定取一个字节
  jz goon
  jmp noequal

goon:
  inc si
  inc di
  dec cx
  jmp compare

equal:
noequal:
  pop ax
  pop di
  pop si
  ret




;指定函数调用参数 传递es:bp 目标字符串的地址 和目标字符串的长度cx
Print:
  mov ax, 0x1301 ;指定打印参数
  mov bx, 0x0007
  int 0x10
  ret

;重置软区函数 no parameter
ResetFloppy:
  push ax
  push dx
  mov ah,0x00
  mov dl,[BS_DrvNum]
  int 0x13
  pop dx
  pop ax
  ret

;读取软区数据
;ax ---->logic sector number
;cx ---->number of sector
;es:bx -----target address
ReadSector:
  push bx;
  push cx;
  push dx;
  push ax;
  call ResetFloppy
  
  push bx;?目标地址的值 放入栈里面
  push cx
  mov bl,[BPB_SecPerTrk];这个地方改变bx 寄存器的值 目标内存地址被改变了 所以没有打印东西? 所以上面需要push一下
  div bl;商在al 余数在ah
  mov cl,ah
  add cl,1 ;扇区号
  mov ch,al
  shr ch,1 ;柱面号
  mov dh,al
  and dh,1;磁头号
  mov dl,[BS_DrvNum];驱动器号

  pop ax ;cx 给ax 扇区的数量
  pop bx;取出目标地址的值

  ;从磁盘将数据读取ES:BX指向的内存中
  mov ah, 0x02
read:
  int 0x13
  jc read ;出错跳转重新读取

  pop ax
  pop dx
  pop cx
  pop bx
  ret

MsgStr db "Hello, DTOS!"
MsgLen equ ($-MsgStr) ;用当前地址-这个地址 = 字符串的长度

DEST db "MAIN    CPP"
TarLen equ ($-DEST)
Buf:
  times 510-($-$$) db 0x00
  db 0x55, 0xaa
